package com.example.littlexs.rxjavademo.http;

import android.util.Log;

import com.example.littlexs.rxjavademo.MyApp;
import com.example.littlexs.rxjavademo.model.MovieResultDO;
import com.example.littlexs.rxjavademo.utils.DeviceUtils;
import com.example.littlexs.rxjavademo.utils.EncryptUtils;
import com.example.littlexs.rxjavademo.utils.StringUtils;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

/**
 * Created by littlexs on 2016/9/21.
 */
public class MyApi {

    private static String BASE_URL = "https://api.douban.com/v2/movie/";
    private static final int DEFAULT_TIMEOUT = 5;//max connection time
    private static Retrofit retrofit;
    public static MyService myService;

    private static OkHttpClient client;
    static HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();

    private static Retrofit getRetrofit(){
        if (retrofit == null) {
            //手动创建一个OkHttpClient并设置超时时间
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            client = new OkHttpClient.Builder()
                    .addInterceptor(loggingInterceptor)
                    .addInterceptor(new SignInterceptor())
                    .build();
            retrofit = new Retrofit.Builder()
                    .client(builder.build())
                    .addConverterFactory(GsonConverterFactory.create())
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .baseUrl(BASE_URL)
                    .build();
        }
        return retrofit;
    }

    public static MyService getService() {
        if (myService == null) {
            myService = getRetrofit().create(MyService.class);
        }
        return myService;
    }

    /**
     * 对 Observable<T> 做统一的处理，处理了线程调度、分割返回结果等操作组合了起来
     * @param responseObservable
     * @param <T>
     * @return
     */
    protected <T > Observable<T> applySchedulers(Observable<T> responseObservable) {
        return responseObservable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .flatMap(new Func1<T, Observable<T>>() {
                    @Override
                    public Observable<T> call(T tResponse) {
                        return flatResponse(tResponse);
                    }
                });
    }

    /**
     * 对网络接口返回的Response进行分割操作 对于jasn 解析错误以及返回的 响应实体为空的情况
     * @param response
     * @return
     */
    public < T > Observable<T> flatResponse(final T response) {
        return Observable.create(new Observable.OnSubscribe<T>() {
            @Override
            public void call(Subscriber<? super T> subscriber) {
                if (response != null) {
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.onNext(response);
                    }
                } else {
                    if (!subscriber.isUnsubscribed()) {
                        subscriber.onError(new APIException("自定义异常类型", "解析json错误或者服务器返回空的json"));
                    }
                    return;
                }
                if (!subscriber.isUnsubscribed()) {
                    subscriber.onCompleted();
                }

            }
        });
    }

    /**
     *
     */
    public static class APIException extends Exception {
        public String code;
        public String message;

        public APIException(String code, String message) {
            this.code = code;
            this.message = message;
        }

        @Override
        public String getMessage() {
            return message;
        }

    }


    private static String sign(String nonce, String timestamp) {
        StringBuilder sb = new StringBuilder();
        sb.append("wBH4YJUYIa6a").append(nonce).append(timestamp);
        return EncryptUtils.sha1(sb.toString());

    }

    private static class SignInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();
            if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
                return chain.proceed(originalRequest);
            }
            String nonce = StringUtils.getRandomString(8);
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
            Request compressedRequest = null;
            Log.i("request",originalRequest.url().encodedPath());
            HttpUrl modifiedUrl = originalRequest.url().newBuilder()
                    .addQueryParameter("platform", "android")
                    .addQueryParameter("version", DeviceUtils.getVersion(MyApp.getInstance().getApplicationContext()))
                    .addQueryParameter("model",android.os.Build.MODEL)
                    .addQueryParameter("os_version",android.os.Build.VERSION.RELEASE)
                    .build();
            compressedRequest = originalRequest.newBuilder().url(modifiedUrl)
                    .header("App-Key", "uwd1c0sxdoyn1")
                    .header("Nonce", nonce)
                    .header("Timestamp", timestamp)
                    .addHeader("Signature", sign(nonce, timestamp))
                    // .cacheControl(CacheControl.FORCE_CACHE)
                    .build();
   /*         //不需要公共参数的接口比如:动态和活动列表
            if(originalRequest.url().encodedPath().equals("/mobile/active/activeList")||
                    originalRequest.url().encodedPath().equals("/mobile/tianjie/member/thirdLogin")||
                    originalRequest.url().encodedPath().equals("/mobile/tianjie/member/thirdregistWithVillage")||
                    originalRequest.url().encodedPath().equals("/mobile/tianjie/member/loginOut")){
                AddPostParamRequestBody newBody = new AddPostParamRequestBody(originalRequest.body(), getParamWithOutMemberId());
                compressedRequest = originalRequest.newBuilder()
                        .header("App-Key", "uwd1c0sxdoyn1")
                        .header("Nonce", nonce)
                        .header("Timestamp", timestamp)
                        .addHeader("Signature", sign(nonce, timestamp))
                        .method(originalRequest.method(), newBody)
                        .build();
            }else{
                AddPostParamRequestBody newBody = new AddPostParamRequestBody(originalRequest.body(), getDeviceInfo());
                compressedRequest = originalRequest.newBuilder()
                        .header("App-Key", "uwd1c0sxdoyn1")
                        .header("Nonce", nonce)
                        .header("Timestamp", timestamp)
                        .header("Cache-Control", String.format("max-age=%d", 60))
                        .addHeader("Signature", sign(nonce, timestamp))
                        .method(originalRequest.method(), newBody)
                        .build();
            }*/
            Response response = chain.proceed(compressedRequest);

            // 无网络时，设置超时为4周
            int maxStale = 60 * 60 * 24 * 28;
            response.newBuilder()
                    .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                    .removeHeader("nyn")
                    .build();
            return response;
        }
    }
}
